from machine import Pin, SPI, PWM
import framebuf
import utime as time
import Color, led

DC = 9
RST = 7
SCK = 10
CS = 13
DIN = 11


# 定义RGB666格式的帧缓冲区类
class FrameBuffer:
    def __init__(self, width, height, colMod='RGB_666'):
        self.width = width
        self.height = height
        self.colMod = colMod
        if colMod == 'RGB_666':
            self.byte_per_pixel = 3
            self.buffer = bytearray(self.width * self.height * 3)  # 3字节表示一个像素的RGB666数据
        elif colMod == 'RGB_565':
            self.byte_per_pixel = 2
            self.buffer = bytearray(self.width * self.height * 2)
        else:
            raise TypeError(f"不支持的 ColorMod: {colMod}")

    # 设置像素颜色
    def set_pixel(self, x, y, color):
        if 0 <= x < self.width and 0 <= y < self.height:
            index = (y * self.width + x) * self.byte_per_pixel
            for i in range(self.byte_per_pixel):
                self.buffer[index + i] = color[i]

    # 填充整个屏幕
    def fill(self, color):
        # 将颜色值填充到buffer中
        for i in range(len(self.buffer) // self.byte_per_pixel):
            for j in range(self.byte_per_pixel):
                self.buffer[i * self.byte_per_pixel + j] = color[j]
        # print(f"Red: {bin(color[0])}, Green: {bin(color[1])}, Blue: {bin(color[2])}")

    def clear(self):
        self.buffer = bytearray(self.width * self.height * self.byte_per_pixel)


class LCD_1inch14(FrameBuffer):
    def __init__(self, colMod):
        self.width = 240
        self.height = 135
        super().__init__(self.width, self.height, colMod)  # 初始化继承自FrameBufferRGB666的类

        self.cs = Pin(CS, Pin.OUT)
        self.cs(1)

        self.rst = Pin(RST, Pin.OUT)

        self.spi = SPI(1, 600_000_000, polarity=0, phase=0, sck=Pin(SCK), mosi=Pin(DIN), miso=None)

        self.dc = Pin(DC, Pin.OUT)
        self.dc(1)

        self.buffer = bytearray(self.height * self.width * self.byte_per_pixel)  # 使用RGB666格式，每像素3字节
        self.init_display()

    def write_cmd(self, cmd):
        self.cs(1)
        self.dc(0)
        self.cs(0)
        self.spi.write(bytearray([cmd]))
        self.cs(1)

    def write_data(self, buf):
        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(bytearray([buf]))
        self.cs(1)

    def init_display(self):
        # Reset the display
        self.rst(1)
        self.rst(0)
        self.rst(1)

        # Memory Data Access Control（P215）
        self.write_cmd(0x36)
        self.write_data(0x70)  # MY, MX, MV, ML, RGB order etc.

        # Set ColorMod（P224）
        self.write_cmd(0x3A)
        if self.colMod == 'RGB_565':
            self.write_data(0x55)  # 16-bit/pixel RGB565,
        elif self.colMod == 'RGB_666':
            self.write_data(0x66)  # 18-bit/pixel RGB666

        # Porch Setting（P263）
        self.write_cmd(0xB2)
        self.write_data(0x0C)
        self.write_data(0x0C)
        self.write_data(0x00)
        self.write_data(0x33)
        self.write_data(0x33)

        # Gate Control（P267）
        self.write_cmd(0xB7)
        self.write_data(0x35)  # VGH=13.26V, VGL=-10.43V

        # VCOM Setting（P272）
        self.write_cmd(0xBB)
        self.write_data(0x19)  # VCOM=0.725V

        # LCM Control（P276）
        self.write_cmd(0xC0)
        self.write_data(0x2C)

        # VDV and VRH Command Enable（P278）
        self.write_cmd(0xC2)
        self.write_data(0x01)

        # VRH Set（P279）
        self.write_cmd(0xC3)
        self.write_data(0x12)

        # VDV Set（P281）
        self.write_cmd(0xC4)
        self.write_data(0x20)

        # Frame Rate Control in Normal Mode（P285）
        self.write_cmd(0xC6)
        self.write_data(0x0F)  # Frame rate=60Hz

        # Power control（P291）
        self.write_cmd(0xD0)
        self.write_data(0xA4)
        self.write_data(0xA1)

        # Positive Voltage Gamma Control（P295）
        self.write_cmd(0xE0)
        self.write_data(0xD0)
        self.write_data(0x04)
        self.write_data(0x0D)
        self.write_data(0x11)
        self.write_data(0x13)
        self.write_data(0x2B)
        self.write_data(0x3F)
        self.write_data(0x54)
        self.write_data(0x4C)
        self.write_data(0x18)
        self.write_data(0x0D)
        self.write_data(0x0B)
        self.write_data(0x1F)
        self.write_data(0x23)

        # Voltage Gamma Control（P297）
        self.write_cmd(0xE1)
        self.write_data(0xD0)
        self.write_data(0x04)
        self.write_data(0x0C)
        self.write_data(0x11)
        self.write_data(0x13)
        self.write_data(0x2C)
        self.write_data(0x3F)
        self.write_data(0x44)
        self.write_data(0x51)
        self.write_data(0x2F)
        self.write_data(0x1F)
        self.write_data(0x1F)
        self.write_data(0x20)
        self.write_data(0x23)

        # Display Inversion On（P190）
        self.write_cmd(0x21)

        # Exit Sleep mode（P182）
        self.write_cmd(0x11)

        # Display On（P196）
        self.write_cmd(0x29)

        # Column Address Set（P198）
        self.write_cmd(0x2A)
        self.write_data(0x00)
        self.write_data(0x28)
        self.write_data(0x01)
        self.write_data(0x17)

        # Row Address Set（P200）
        self.write_cmd(0x2B)
        self.write_data(0x00)
        self.write_data(0x35)
        self.write_data(0x00)
        self.write_data(0xBB)

    def show(self):
        # Memory Write（P202）
        self.write_cmd(0x2C)

        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(self.buffer)
        self.cs(1)


if __name__ == '__main__':
    key1 = Pin(18, Pin.IN, Pin.PULL_UP)
    key2 = Pin(19, Pin.IN, Pin.PULL_UP)

    LCD = LCD_1inch14(colMod='RGB_666')

    LCD.fill(Color.typical['black'].RGB_666())
    LCD.show()
    print('start')

    i = -1
    count_time, t0 = 0, time.time()
    while count_time < 10:
        count_time = time.time()-t0
        if i > 0 and key2.value() == 0:
            t0 = time.time()
            i -= 1
        elif i < len(list(Color.typical)) - 1 and key1.value() == 0:
            t0 = time.time()
            i += 1
        else:
            continue

        col = list(Color.typical)[i]
        print(col)

        led.led256(*Color.typical[col].RGB())
        LCD.fill(Color.typical[col].RGB_666())
        LCD.show()

    print('end')
    LCD.fill(Color.typical['black'].RGB_666())
    LCD.show()
    led.led256(0,0,0)